﻿using Common.Communication;
using Common.Device.DeviceDb;
using Common.Device.Enums;
using Common.Device.Interfaces;
using Common.Tool.DataTools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.Remoting.Channels;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ShiBoQi
{
    public class DHO1202NiVisa:NiVisaBase, IShiBoQi
    {
        public string Name { get; set; }
        public DHO1202NiVisa(UseDevice device) : base($"USB0::0x1AB1::0x0610::{device.parameter}::INSTR", 1500)
        {
            Name = device.name;
        }
        public Result<double> GetVpp(int channel, ShiBoQiEnum.TimeDiv time, ShiBoQiEnum.VolDiv vol, ShiBoQiEnum.Coup coupling, ShiBoQiEnum.Limit bwLimit,int wait)
        {
            lock (this)
            {
                var result = new Result<double>();
                var write = new Result();
                var read = new Result<string>();
                string timeDiv = "";
                switch (time)
                {
                    case ShiBoQiEnum.TimeDiv._1uS: timeDiv = "0.000001"; break;
                    case ShiBoQiEnum.TimeDiv._2uS: timeDiv = "0.000002"; break;
                    case ShiBoQiEnum.TimeDiv._5uS: timeDiv = "0.000005"; break;
                    case ShiBoQiEnum.TimeDiv._10uS: timeDiv = "0.00001"; break;
                    case ShiBoQiEnum.TimeDiv._20uS: timeDiv = "0.00002"; break;
                    case ShiBoQiEnum.TimeDiv._50uS: timeDiv = "0.00005"; break;
                    case ShiBoQiEnum.TimeDiv._100uS: timeDiv = "0.0001"; break;
                    case ShiBoQiEnum.TimeDiv._200uS: timeDiv = "0.0002"; break;
                    case ShiBoQiEnum.TimeDiv._500uS: timeDiv = "0.0005"; break;
                    case ShiBoQiEnum.TimeDiv._1mS: timeDiv = "0.001"; break;
                    case ShiBoQiEnum.TimeDiv._2mS: timeDiv = "0.002"; break;
                    case ShiBoQiEnum.TimeDiv._5mS: timeDiv = "0.005"; break;
                    case ShiBoQiEnum.TimeDiv._10mS: timeDiv = "0.01"; break;
                    case ShiBoQiEnum.TimeDiv._20mS: timeDiv = "0.02"; break;
                    case ShiBoQiEnum.TimeDiv._50mS: timeDiv = "0.05"; break;
                    case ShiBoQiEnum.TimeDiv._100mS: timeDiv = "0.1"; break;
                    case ShiBoQiEnum.TimeDiv._200mS: timeDiv = "0.2"; break;
                    case ShiBoQiEnum.TimeDiv._500mS: timeDiv = "0.5"; break;
                    case ShiBoQiEnum.TimeDiv._1S: timeDiv = "1"; break;
                    case ShiBoQiEnum.TimeDiv._2S: timeDiv = "2"; break;
                    case ShiBoQiEnum.TimeDiv._5S: timeDiv = "5"; break;
                    case ShiBoQiEnum.TimeDiv._10S: timeDiv = "10"; break;
                    case ShiBoQiEnum.TimeDiv._20S: timeDiv = "20"; break;
                    case ShiBoQiEnum.TimeDiv._50S: timeDiv = "50"; break;
                    default:
                        result.Err = "时基选择错误";
                        result.IsSucceed = false;
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                }
                AppendInfo(Name, $"设置主时基");
                write = Write(CmdSetMainTimeBase);
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置主时基失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                read = WriteThenRead(CmdGetTimeBase);
                if (!read.IsSucceed || !read.Value.Trim().Equals(CmdSetMainTimeBaseOk))
                {
                    result.IsSucceed = false;
                    result.Err = "设置主时基失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                //AppendInfo(Name, $"打开XY时基模式");
                //write = Write(CmdSetTimeFormatXY);
                //if (!write.IsSucceed)
                //{
                //    result.IsSucceed = false;
                //    result.Err = "打开XY时基模式失败";
                //    AppendTip(Name, result.Err);
                //    return result.EndTime();
                //}
                //Thread.Sleep(100);
                //read = WriteThenRead(CmdGetTimeFormat);
                //if (!read.IsSucceed || !read.Value.Trim().Equals("1"))
                //{
                //    result.IsSucceed = false;
                //    result.Err = "打开XY时基模式失败";
                //    AppendTip(Name, result.Err);
                //    return result.EndTime();
                //}
                AppendInfo(Name, $"设置主时基{time}");
                write = Write(CmdSetTimeScale(timeDiv));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置主时基失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                read = WriteThenRead(CmdGetTimeScale);
                if (!read.IsSucceed || !double.TryParse(read.Value, out double t) || t != double .Parse(timeDiv))
                {
                    result.IsSucceed = false;
                    result.Err = "设置主时基失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                string probe = "";
                string volDiv = "";//电压档位
                switch (vol)
                {
                    case ShiBoQiEnum.VolDiv._2mV: probe = "1"; volDiv = "0.002"; break;
                    case ShiBoQiEnum.VolDiv._5mV: probe = "1"; volDiv = "0.005"; break;
                    case ShiBoQiEnum.VolDiv._10mV: probe = "1"; volDiv = "0.01"; break;
                    case ShiBoQiEnum.VolDiv._20mV: probe = "1"; volDiv = "0.02"; break;
                    case ShiBoQiEnum.VolDiv._50mV: probe = "1"; volDiv = "0.05"; break;
                    case ShiBoQiEnum.VolDiv._100mV: probe = "1"; volDiv = "0.1"; break;
                    case ShiBoQiEnum.VolDiv._200mV: probe = "1"; volDiv = "0.2"; break;
                    case ShiBoQiEnum.VolDiv._500mV: probe = "1"; volDiv = "0.5"; break;
                    case ShiBoQiEnum.VolDiv._1V: probe = "1"; volDiv = "1"; break;
                    case ShiBoQiEnum.VolDiv._2V: probe = "1"; volDiv = "2"; break;
                    case ShiBoQiEnum.VolDiv._5V: probe = "1"; volDiv = "5"; break;
                    case ShiBoQiEnum.VolDiv._10V: probe = "1"; volDiv = "10"; break;
                    default:
                        result.Err = "电压档位选择错误";
                        result.IsSucceed = false;
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                }
                AppendInfo(Name, $"设置通道{channel}衰减因素{probe}");
                write = Write(CmdSetProbe(channel, probe));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置衰减因素失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                read = WriteThenRead(CmdGetProbe(channel));
                if (!read.IsSucceed || !read.Value.Trim().Equals(probe))
                {
                    result.IsSucceed = false;
                    result.Err = "设置衰减因素失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置通道{channel}电压档位{vol}");
                write = Write(CmdSetChannelScale(channel, volDiv));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置电压档位失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                read = WriteThenRead(CmdGetChannelScale(channel));
                if (!read.IsSucceed || !double.TryParse(read.Value, out double v) || v != double.Parse(volDiv))
                {
                    result.IsSucceed = false;
                    result.Err = "设置电压档位失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置通道{channel}耦合方式{coupling.ToString()}");
                write = Write(CmdSetCoupling(channel, coupling.ToString()));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置耦合方式失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                read = WriteThenRead(CmdGetCoupling(channel));
                if (!read.IsSucceed || !read.Value.Trim().Equals(coupling.ToString()))
                {
                    result.IsSucceed = false;
                    result.Err = "设置耦合方式失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                string limit="";
                switch (bwLimit)
                {
                    case ShiBoQiEnum.Limit._20M:limit = "20M"; break;
                    case ShiBoQiEnum.Limit.OFF:limit = "OFF"; break;
                    default:
                        result.Err = "带宽限制选择错误";
                        result.IsSucceed = false;
                        AppendTip(Name, result.Err);
                        return result.EndTime();
                }
                AppendInfo(Name, $"设置通道{channel}带宽限制{limit}");
                write = Write(CmdSetBwLimit(channel, limit));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置带宽限制失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                read = WriteThenRead(CmdGetBwLimit(channel));
                if (!read.IsSucceed || !read.Value.Trim().Equals(limit))
                {
                    result.IsSucceed = false;
                    result.Err = "设置带宽限制失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置通道{channel}峰峰值采集");
                write = Write(CmdSetVpp(channel));
                if (!write.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置峰峰值采集失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                Task.Delay(wait).Wait();
                read = WriteThenRead(CmdMeasureVpp(channel));
                if (!read.IsSucceed || !double.TryParse(read.Value, out double vpp))
                {
                    result.IsSucceed = false;
                    result.Err = "读取当前峰峰值失败";
                    AppendTip(Name, result.Err);
                    return result.EndTime();
                }
                result.Value = vpp;
                AppendResult(Name, DataConvert.ToUnit(vpp, "F3") + "V");
                return result.EndTime();
            }
        }

        /// <summary>
        /// 通道
        /// </summary>
        List<string> Channels = new List<string>()
        {
            "1",
            "2"
        };
        /// <summary>
        /// 电压档位
        /// </summary>
        List<string> VolDivs = new List<string>()
        {
            "2mV",
            "5mV",
            "10mV",
            "20mV",
            "50mV",
            "100mV",
            "200mV",
            "500mV",
            "1V",
            "2V",
            "5V",
            "10V"
        };
        /// <summary>
        /// 时基
        /// </summary>
        List<string> TimeDivs = new List<string>()
        {
            "5nS",
            "10nS",
            "20nS",
            "50nS",
            "100nS",
            "200nS",
            "500nS",
            "1uS",
            "2uS",
            "5uS",
            "10uS",
            "20uS",
            "50uS",
            "100uS",
            "200uS",
            "500uS",
            "1mS",
            "2mS",
            "5mS",
            "10mS",
            "20mS",
            "50mS",
            "100mS",
            "200mS",
            "500mS",
            "1S",
            "2S",
            "5S",
            "10S",
            "20S",
            "50S",
        };
        /// <summary>
        /// 耦合方式
        /// </summary>
        List<string> Coups = new List<string>()
        {
            "直流",
            "交流",
            "接地"
        };
        /// <summary>
        /// 带宽限制
        /// </summary>
        List<string> Limits = new List<string>()
        {
            "开启",
            "关闭"
        };
        /// <summary>
        /// 设置探头衰减因数
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="attn"></param>
        /// <returns></returns>
        string CmdSetProbe(int channel, string attn) { return $":CHANnel{channel}:PROBe {attn}\r\n"; }
        string CmdGetProbe(int channel) { return $":CHANnel{channel}:PROBe?\r\n"; }
        /// <summary>
        /// 设置垂直档位
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="range"></param>
        /// <returns></returns>
        string CmdSetChannelScale(int channel, string range) { return $":CHANnel{channel}:SCALe {range}\r\n"; }
        string CmdGetChannelScale(int channel) { return $":CHANnel{channel}:SCALe?\r\n"; }
        /// <summary>
        /// 设置主时基
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="range"></param>
        /// <returns></returns>
        string CmdSetMainTimeBase { get => $":TIM:MODE MAIN\r\n"; }
        string CmdSetMainTimeBaseOk { get => $"MAIN"; }
        string CmdGetTimeBase { get => $":TIM:MODE?\r\n"; }
        string CmdSetTimeFormatXY { get => $":TIMebase:XY:ENABle true\r\n"; }
        string CmdGetTimeFormat { get => $":TIMebase:XY:ENABle?\r\n"; }
        string CmdSetTimeFormatXYOk { get => $"true"; }
        string CmdSetTimeScale(string second) { return $":TIMebase:MAIN:SCALe {second}\r\n"; }
        string CmdGetTimeScale { get => $":TIMebase:MAIN:SCALe?\r\n"; }
        /// <summary>
        /// 耦合方式
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        string CmdSetCoupling(int channel, string type) { return $":CHANnel{channel}:COUP {type}\r\n"; }
        string CmdGetCoupling(int channel) { return $":CHANnel{channel}:COUP?\r\n"; }
        /// <summary>
        /// 带宽限制
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        string CmdSetBwLimit(int channel, string mode) { return $":CHAN{channel}:BWL {mode}\r\n"; }
        string CmdGetBwLimit(int channel) { return $":CHAN{channel}:BWL?\r\n"; }
        string CmdSetVpp(int channel) { return $":MEASure:STATistic:ITEM VPP,CHANnel{channel}\r\n"; }
        string CmdMeasureVpp(int channel) { return $":MEASure:STATistic:ITEM? MAXimum,VPP,CHANnel{channel}\r\n"; }

    }
}
